package grafica; 

import java.awt.Graphics;
import java.awt.Rectangle;

/**
 * Una Entity representa gráficamente a cualquier entidad del juego gráficamente.
 * Esta clase se baso parcialmente en el tutorial de Kevin Glass 
 * "Space Invaders 101, An Accelerated Java 2D Tutorial"
 * 
 * @author Amorosi, Javier (94528)
 * @author Antiman, Nehuen (102440)
 */
public abstract class Entity {
	
	protected ControlGraficos game;
	
	//Posicion en la matriz lógica del juego.
	protected int f;
	protected int c; 
	
	//Posición y velocidad en pixeles.
	protected double x;
	protected double y;
	protected double dx;
	protected double dy;

	protected double orientacionGrados; 
	
	protected Sprite sprite;
	
	protected Rectangle me = new Rectangle();
	protected Rectangle him = new Rectangle();

	private int pix;
	
	/**
	 * Constructor de la clase Entity
	 * 
	 * Si bien se reciben como parámetros la fila y la columna como
	 * posicion de la entidad, estos parámetros seran mapeados a 
	 * píxeles. 
	 * 
	 * @param _game el juego donde participa la entidad. 
	 * @param ref Referencia al sprite que mostrará la Entity.
 	 * @param f fila inicial en lógica de la entidad.
	 * @param c columna inicial en lógica de la entidad.
	 */
	public Entity(ControlGraficos _game, String ref,int f, int c) {
		this.sprite = SpriteStore.get().getSprite(ref);
		this.f = f;
		this.c = c;
		game=_game;
		pix=game.getPixelesImagenes();
		x=pix*c;
		y=pix*f;
	}
	
	/**
	 * Se le pide a la entidad que se mueva basada en un cierto tiempo que ha transcurrido.
	 * 
	 * @param delta tiempo que ha transcurrido en milisegundos.
	 */
	public void move(long delta) {
		x += (delta * dx) / 1000;
		y += (delta * dy) / 1000;
	}
	
	/**
	 * Establece la velocidad horizontal de la entidad.
	 * 
	 * @param dx velocidad horizontal de la entidad (pixeles/segundos).
	 */
	public void setHorizontalMovement(double dx) {
		this.dx = dx;
	}

	/**
	 * Establece la velocidad vertical de la entidad.
	 * 
	 * @param dy velocidad vertical de la entidad (pixeles/segundos).
	 */
	public void setVerticalMovement(double dy) {
		this.dy = dy;
	}
	
	/**
	 * Retorna la velocidad horizontal de la entidad.
	 * 
	 * @return velocidad horizontal.
	 */
	public double getHorizontalMovement() {
		return dx;
	}

	/**
	 * Retorna la velocidad vertical de la entidad.
	 * 
	 * @return velocidad vertical.
	 */
	public double getVerticalMovement() {
		return dy;
	}
	
	/**
	 * Dibuja la entidad en el gráfico provisto.
	 * 
	 * @param g El gráfico en cual se dibujará.
	 */
	public void draw(Graphics g) {
		sprite.draw(g,(int) x,(int) y);
	}
	
	/**
	 * Dibuja la entidad en el gráfico provisto, pero rotada segun su orientacion en grados lo indique.
	 * 
	 * @param g El gráfico en cual se dibujará.
	 */
	public void drawRotated(Graphics g){
		sprite.drawRotated(g,(int) x, (int) y, orientacionGrados);
	}
		
	/**
	 * Establece la posicion en filas de la entidad.
	 * @param f fila.
	 */
	public void setF(int f){
		this.f=f;
		y=pix*f;
	}
	
	/**
	 * Establece la posicion en columnas de la entidad.
	 * @param c columna.
	 */
	public void setC(int c){
		this.c=c;
		x=pix*c;
	}
	
	/**
	 * Retorna la posicion en filas de la entidad.
	 * @return la posicion en filas de la entidad.
	 */
	public int getF(){
		return f;
	}
	
	/**
	 * Retorna la posicion en columnas de la entidad.
	 * @return la posicion en columnas de la entidad.
	 */
	public int getC(){
		return c;
	}
	
	/**
	 * Retorna la posicion en X en píxeles de la entidad.
	 * 
	 * @return X en píxeles de la entidad.
	 */
	public int getX() {
		return (int) x;
	}

	/**
	 * Retorna la posicion en Y en píxeles de la entidad.
	 * 
	 * @return Y en píxeles de la entidad.
	 */
	public int getY() {
		return (int) y;
	}
	
	/**
	 * Verifica si esta entidad a colisionado con otra entidad. 
	 * Se entinde por colision que las entidades se intersectan graficamente en un 
	 * rectangulo de al menos 20x20 píxeles.
	 * 
	 * @param other la otra entidad con la que se quiere verificar la colisión.
	 * @return true si las entidades colisionaron, false caso contrario.
	 */
	public boolean collidesWith(Entity other) {
		me.setBounds((int) x,(int) y,sprite.getWidth(),sprite.getHeight());
        him.setBounds((int) other.x,(int) other.y,other.sprite.getWidth(),other.sprite.getHeight());
        Rectangle r=me.intersection(him);        
        return (r.getHeight()>20 && r.getWidth()>20);
		
	}
	
	/**
	 * Se le notifica a esta entidad que ha colisionado con otra entidad. 
	 * 
	 * @param other la otra entidad con la que ha colisionado. 
	 */
	public abstract void collidedWith(Entity other);
	
	/**
	 * Cambia el sprite actual de la entidad.
	 * @param ref referencia al nuevo sprite. 
	 */
	public void changeSprite(String ref){
		this.sprite = SpriteStore.get().getSprite(ref);
	}
}